{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 对Song做基于item的协同过滤"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "#load数据（用户和物品索引，以及倒排表）\n",
    "import pickle as pk\n",
    "\n",
    "#稀疏矩阵，打分表\n",
    "import scipy.io as sio\n",
    "import os\n",
    "\n",
    "import scipy.spatial.distance as ssd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "temp_data = './temp_data/'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#读取预备数据\n",
    "users_index = pk.load(open(temp_data + \"users_index.pkl\", 'rb'))\n",
    "items_index = pk.load(open(temp_data + \"items_index.pkl\", 'rb'))\n",
    "user_2_items = pk.load(open(temp_data + \"user_2_items.pkl\", 'rb'))\n",
    "item_2_users = pk.load(open(temp_data + \"item_2_users.pkl\", 'rb'))\n",
    "\n",
    "user_item_2_score = sio.mmread(temp_data + \"user_item_2_score\").tocsr()\n",
    "\n",
    "n_users = len(users_index)\n",
    "n_items = len(items_index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 14.10714286,  22.57894737,   3.38461538,   5.35      ,\n",
       "        13.85714286,  30.625     ,   3.56626506,   4.6       ,\n",
       "         6.26086957,   5.71428571,   1.875     ,   4.46846847,\n",
       "         1.83529412,   5.58730159,   8.68421053,   6.13888889,\n",
       "        13.88888889,   2.59016393,   2.29545455,   2.52941176,\n",
       "         3.77419355,   4.24848485,   6.4375    ,   2.84615385,\n",
       "         6.23134328,  12.42982456,   6.65662651,   2.40350877,\n",
       "        26.5       ,  11.07692308,   3.67567568,  15.6875    ,\n",
       "         8.53448276,   6.4137931 ,   4.29885057,   8.74842767,\n",
       "         1.16783217,   4.57142857,   5.93630573,   7.04132231,\n",
       "         4.04123711,   1.6       ,   2.79032258,  48.2       ,\n",
       "         3.6969697 ,   2.20408163,  14.25      ,   5.43589744,\n",
       "         3.95238095,   9.13333333,   4.27071823,   4.46666667,\n",
       "         3.82608696,   2.36363636,   2.97560976,   3.82978723,\n",
       "        41.125     ,   4.49019608,   6.05607477,   4.04166667,\n",
       "         6.74193548,   4.30985915,   0.73      ,  23.4       ,\n",
       "         4.75490196,   7.3982684 ,   4.64285714,   8.69444444,\n",
       "        43.75      ,   5.84375   ,   9.75862069,   2.72881356,\n",
       "         4.20289855,   1.55      ,   2.55384615,  19.04347826,\n",
       "         6.37837838,   5.04716981,   4.33333333,   4.19101124,\n",
       "         1.15789474,   6.925     ,   6.00699301,   2.425     ,\n",
       "        13.16666667,   5.83221477,   4.46031746,  26.85      ,\n",
       "        14.13333333,   9.80530973,   2.59813084,   6.46060606,\n",
       "         8.73295455,   4.21428571,   2.18095238,   7.28888889,\n",
       "         3.87209302,   7.05952381,   6.02439024,  14.01265823,\n",
       "         8.15217391,  28.40740741,  17.9       ,  12.61904762,\n",
       "         7.41791045,   3.06818182,   9.24378109,   4.56666667,\n",
       "         1.61538462,   8.72881356,  12.15384615,   1.97142857,\n",
       "         4.61904762,  11.61538462,   1.49586777,  13.7       ,\n",
       "         0.76190476,   3.23684211,   5.10344828,   5.23529412,\n",
       "        15.435     ,   4.59836066,   2.0125    ,   4.85714286,\n",
       "         3.69014085,   9.8125    ,   2.86466165,  20.70588235,\n",
       "         6.59360731,  18.89705882,  16.55172414,   2.98795181,\n",
       "         0.80434783,   6.4       ,  13.76470588,  14.05813953,\n",
       "         3.55932203,   1.5625    ,   5.        ,   4.63829787,\n",
       "         4.44680851,   2.04761905,   8.56896552,   4.23255814,\n",
       "         8.21311475,   3.        ,   2.76      ,   2.01639344,\n",
       "        34.83333333,   3.86440678,  35.42857143,   2.44444444,\n",
       "        38.84615385,   5.75      ,   7.7816092 ,   4.65217391,\n",
       "         4.72972973,   7.2962963 ,   2.52631579,   6.5       ,\n",
       "        10.54545455,   3.95238095,   2.06666667,   3.42553191,\n",
       "         3.13559322,   6.5862069 ,  13.51351351,  10.13333333,\n",
       "         3.10416667,   7.58333333,  12.03636364,   8.38571429,\n",
       "         4.73684211,   7.7       ,  15.2       ,  19.58333333,\n",
       "         4.17307692,   1.19672131,   3.12328767,   1.69230769,\n",
       "        20.36734694,  25.        ,  11.09090909,   5.5       ,\n",
       "         3.84090909,   8.07894737,   5.14705882,   2.78313253,\n",
       "        40.83333333,   3.97272727,   4.5042735 ,   1.28205128,\n",
       "         3.82142857,   4.77419355,   2.10344828,   3.09677419,\n",
       "         5.86885246,  16.15      ,   1.1125    ,   2.55384615,\n",
       "         3.40540541,   0.8       ,   8.        ,   9.07142857,\n",
       "         3.28571429,  35.22222222,   6.01282051,   4.80645161,\n",
       "         2.21212121,   9.36842105,   4.46376812,   4.08695652,\n",
       "        15.2173913 ,   5.65      ,   6.63636364,   5.5       ,\n",
       "         2.85      ,   3.32075472,   8.07142857,   3.06153846,\n",
       "         4.95454545,  16.84      ,   5.5       ,   7.32653061,\n",
       "         5.15454545,   0.34883721,  13.51515152,   6.57142857,\n",
       "         5.05479452,  11.39285714,   9.69230769,  14.48648649,\n",
       "         2.77272727,   0.22222222,   7.25581395,   9.12857143,\n",
       "         3.01136364,   3.44      ,   5.89230769,  11.47619048,\n",
       "         2.96491228,   2.4137931 ,  17.96428571,   8.96428571,\n",
       "         8.54054054,   2.62068966,   4.77564103,  15.60869565,\n",
       "         9.53488372,   2.375     ,   5.70588235,   6.4137931 ,\n",
       "        13.76470588,   3.35      ,   1.03603604,   0.        ,\n",
       "         8.42424242,   6.05555556,   4.12631579,  31.08      ,\n",
       "         6.17857143,   1.79591837,   3.42857143,   4.48076923,\n",
       "         4.59259259,   4.48648649,  20.26923077,   3.        ,\n",
       "         8.43333333,  11.4       ,   4.83      ,   8.47826087,\n",
       "         8.5       ,   0.60606061,   1.56756757,   2.75      ,\n",
       "         4.16853933,  15.71794872,  10.27631579,   3.112     ,\n",
       "         5.74074074,   6.51912568,  10.5       ,   5.43529412,\n",
       "         1.14583333,   6.71428571,   1.49152542,  15.35      ,\n",
       "         6.3       ,   3.4       ,  48.55555556,  37.1875    ,\n",
       "        91.44444444,  11.66666667,   5.85714286,   1.24324324,\n",
       "        13.66666667,   9.47826087,   8.62162162,   3.06976744,\n",
       "        17.4       ,  10.84615385,  32.6       ,   4.45714286,\n",
       "         5.10344828,   1.82608696,   9.37735849,  36.2       ,\n",
       "         4.44444444,   5.92105263,   5.38636364,   2.83018868,\n",
       "         6.36065574,  20.71428571,   6.97014925,  28.8125    ,\n",
       "         6.28378378,   3.7       ,   3.78571429,  14.7       ,\n",
       "         9.4       ,  23.86554622,   3.57894737,   2.41463415,\n",
       "         6.82608696,   4.47222222,   8.8       ,   8.25974026,\n",
       "         6.69230769,   6.76923077,  17.12244898,   2.75757576,\n",
       "        10.24      ,   4.28571429,   3.04545455,  10.90277778,\n",
       "         4.56896552,  14.6       ,   1.25      ,   2.70833333,\n",
       "         9.09090909,  31.66666667,   8.50943396,   1.12048193,\n",
       "         2.36956522,  19.36363636,  37.33333333,   5.88888889,\n",
       "         1.5       ,  11.24      ,   6.8125    ,   4.76576577,\n",
       "         9.        ,   7.73529412,   5.10638298,   5.5       ,\n",
       "        13.72727273,   1.72340426,   2.72727273,  12.76190476,\n",
       "         8.96      ,  13.71111111,   5.01923077,   3.48484848,\n",
       "         8.85714286,   1.890625  ,   2.58823529,   3.36363636,\n",
       "         2.46835443,  13.90243902,   5.62337662,   4.84507042,\n",
       "         4.85365854,   1.47916667,   3.5       ,   2.875     ,\n",
       "         5.23648649,   9.17647059,  10.57142857,  14.30769231,\n",
       "        13.65517241,   5.39622642,   2.27272727,  11.625     ,\n",
       "        27.39130435,  24.        ,  12.71428571,   4.72727273,\n",
       "        15.66666667,  11.79545455,   1.58823529,  61.58333333,\n",
       "         5.11764706,   6.        ,   2.98305085,  10.76315789,\n",
       "        16.78378378,   3.        ,  11.67857143,   1.28571429,\n",
       "         5.4       ,   1.43478261,   8.8       ,   8.43333333,\n",
       "        10.42857143,  20.4375    ,  10.96721311,  12.04347826,\n",
       "        22.18181818,   2.6       ,   8.23255814,  21.75      ,\n",
       "         2.61111111,   6.5       ,   8.3       ,   2.94029851,\n",
       "        21.33333333,   0.13333333,   1.45794393,  34.52941176,\n",
       "        42.05263158,   4.37254902,   1.35714286,  10.52941176,\n",
       "         5.86363636,   4.28169014,   0.24137931,   5.46031746,\n",
       "         6.1641791 ,   6.13333333,   4.89473684,   5.        ,\n",
       "         6.83333333,  19.58333333,   2.73529412,   7.88235294,\n",
       "        20.94736842,  17.26315789,  14.        ,   3.52830189,\n",
       "         0.69230769,   2.17391304,   3.48101266,   3.15217391,\n",
       "         4.21875   ,  16.1875    ,   3.08333333,  12.16666667,\n",
       "        12.44444444,   5.04081633,   6.75      ,   3.77272727,\n",
       "        29.36363636,  14.46666667,   5.81818182,   0.89655172,\n",
       "         2.22222222,   6.17391304,   6.22033898,   5.1025641 ,\n",
       "         1.76470588,  18.66666667,   3.47368421,   5.7962963 ,\n",
       "         3.6969697 ,  18.75      ,  12.02439024,  73.66666667,\n",
       "         5.2       ,   2.58333333,  10.15789474,  11.2173913 ,\n",
       "        16.        ,   3.7       ,   1.6969697 ,   6.85185185,\n",
       "         9.25      ,   5.23809524,   5.17391304,  13.44230769,\n",
       "        63.77777778,   8.17391304,   5.95348837,   9.27272727,\n",
       "        18.26666667,  16.26923077,  27.34782609,   2.2       ,\n",
       "        16.28571429,  14.17647059,   3.60606061,   1.26666667,\n",
       "        13.52380952,  10.875     ,  10.11764706,  31.88888889,\n",
       "         2.84615385,  11.89473684,   1.60784314,   2.16666667,\n",
       "        13.5       ,  16.4       ,   5.25      ,   8.5       ,\n",
       "        33.85714286,  13.80952381,  25.09090909,  29.08333333,\n",
       "        16.71428571,  25.05      ,  52.8       ,   4.35      ,\n",
       "        10.45454545,   4.83333333,   1.29166667,   2.21428571,\n",
       "         6.34      ,   2.16071429,   4.46153846,   4.9375    ,\n",
       "         5.5       ,  23.08333333,   1.18181818,   6.22058824,\n",
       "        18.53125   ,  10.1875    ,  15.17647059,   4.57142857,\n",
       "         8.14285714,   2.95652174,  39.875     ,  20.40909091,\n",
       "         6.94117647,   8.17073171,  11.30769231,   7.86956522,\n",
       "         5.01785714,   2.85      ,   4.31034483,   6.43137255,\n",
       "         4.81132075,  25.44444444,  14.34482759,  22.        ,\n",
       "         2.875     ,   1.91666667,  13.375     ,   1.67741935,\n",
       "         1.66666667,  10.33333333,  11.54545455,   9.93333333,\n",
       "        16.65217391,  10.75675676,  12.5       ,  17.04166667,\n",
       "         2.02325581,   3.44705882,   7.3       ,  20.07692308,\n",
       "         0.33333333,  10.41791045,  43.8       ,   8.82352941,\n",
       "         5.        ,   9.12121212,   4.16666667,  11.        ,\n",
       "         7.10344828,   9.5       ,  43.3125    ,   0.6       ,\n",
       "         4.44444444,  14.        ,  18.55      ,  21.14285714,\n",
       "        11.86206897,  11.75      ,  26.        ,  13.8       ,\n",
       "        14.92857143,  14.        ,  34.66666667,   5.        ,\n",
       "        11.25      ,  26.70588235,  15.04761905,  11.57142857,\n",
       "         7.16666667,   8.26666667,   0.5       ,   2.88461538,\n",
       "        22.83333333,  15.        ,   7.32142857,   0.875     ,\n",
       "         6.83333333,  95.        ,   7.26666667,   9.73913043,\n",
       "        19.33333333,   2.14285714,  40.        ,   2.625     ,\n",
       "        35.33333333,   3.45454545,   5.75      ,   7.03225806,\n",
       "        12.        ,  10.57894737,   6.69565217,  41.23529412,\n",
       "        19.5       ,   4.07142857,  11.75      ,  44.8       ,\n",
       "        17.54545455,  49.16666667,  19.2173913 ,  47.2       ,\n",
       "         3.0625    ,  68.        ,   4.46428571,   4.96428571,\n",
       "         4.3125    ,   8.61111111,  47.84210526,  36.5       ,\n",
       "        42.6       ,  13.72222222,   8.25      ,   2.52941176,\n",
       "        14.        ,   9.69565217,   3.25      ,  36.71428571,\n",
       "        14.11111111,   5.09090909,   6.66666667,  15.71428571,\n",
       "        21.        ,  17.2       ,   3.95238095,  11.75      ,\n",
       "        14.        ,   9.55555556,  14.90909091,  16.        ,\n",
       "         1.875     ,   2.81818182,  26.2       ,  28.42857143,\n",
       "        26.15384615,  11.28125   ,   5.39473684,  15.95      ,\n",
       "        15.46153846,   9.        ,   9.78571429,  17.125     ,\n",
       "         3.48148148,   6.66666667,   5.6       ,   5.        ,\n",
       "         3.4       ,  16.77777778,  52.        ,  11.        ,\n",
       "        38.33333333,   5.        ,  11.41666667,  46.875     ,\n",
       "        23.75      ,   1.        ,   1.25      ,   9.44230769,\n",
       "         5.23076923,  13.        ,  51.375     ,   0.        ,\n",
       "         7.88888889,  12.88888889,   2.96666667,   7.375     ,\n",
       "         1.25      ,   1.9       ,   2.25      ,  16.6       ,\n",
       "        11.16666667,  43.75      ,   3.3       ,   6.        ,\n",
       "        29.14285714,  43.        ,  21.16666667,   8.33333333,\n",
       "         6.28571429,  22.66666667,   3.16666667,  13.23529412,\n",
       "        34.33333333,  13.13333333,  26.        ,  17.        ,\n",
       "        19.23529412,   9.33333333,  41.33333333,   7.33333333,\n",
       "        26.        ,  25.77777778,   6.5       ,  34.8       ,\n",
       "         8.7       ,  29.25      ,   6.        ,  14.8       ,\n",
       "         2.        ,  15.93333333,  28.33333333,  44.83333333,\n",
       "         8.25      ,   1.        ,   2.8       ,  83.4       ,\n",
       "        18.66666667,  65.66666667,  41.14285714,  58.6       ,\n",
       "        54.        ,  36.66666667,  24.5       ,  46.        ,\n",
       "        16.33333333,  27.75      ,   7.3       ,  24.25      ,\n",
       "        50.66666667,  50.58333333,  29.33333333,  15.08333333,\n",
       "        50.        ,  39.2       ,  15.2       ,   3.38461538,\n",
       "        13.75      ,  13.5       ,   2.25      ,  67.28571429,\n",
       "        66.66666667,   0.4       ,  13.        ,  10.25      ,\n",
       "         4.71428571,  14.2       ,  38.2       ,  49.        ,\n",
       "        17.33333333,   1.83333333,  77.6       ,  50.        ,\n",
       "        43.        ,  48.        ,   0.        ,  30.75      ,\n",
       "         6.33333333,  21.44444444,   4.5       ,  20.2       ,\n",
       "         3.        , 100.        ,  12.1       ,  24.        ,\n",
       "        26.        ,  20.        ,  13.5       ,   5.2       ,\n",
       "        75.75      ,  22.83333333,   3.        ,  28.        ,\n",
       "         0.        ,  14.        , 100.        ,  20.        ,\n",
       "         5.        , 100.        ,   0.        ])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#计算每个user的平均打分\n",
    "users_mean_score = np.zeros(n_users)\n",
    "for user_index in range(n_users):\n",
    "    acc = 0.0\n",
    "    cur_user_items_count = 0\n",
    "    for item_index in user_2_items[user_index]:\n",
    "        acc += user_item_2_score[user_index, item_index]\n",
    "        cur_user_items_count += 1\n",
    "    users_mean_score[user_index] = acc/cur_user_items_count\n",
    "users_mean_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cal_sim(item_index_0, item_index_1):\n",
    "    #找出两个item都被同一个user打过分的user集合\n",
    "    if item_index_0 == item_index_1:#同一个item\n",
    "        return 1.0\n",
    "    \n",
    "    both_users = {}\n",
    "    for tmp_user_index in item_2_users[item_index_0]:\n",
    "        if tmp_user_index in item_2_users[item_index_1]:\n",
    "            both_users[tmp_user_index] = 1\n",
    "            \n",
    "    if len(both_users) == 0:\n",
    "        return 0.0 #两item者没有相似度\n",
    "    \n",
    "    #此user对两item的有效打分-此user的平均打分\n",
    "    s0 = np.array([user_item_2_score[tmp_user_index, item_index_0] - users_mean_score[tmp_user_index] for tmp_user_index in both_users])\n",
    "    s1 = np.array([user_item_2_score[tmp_user_index, item_index_1] - users_mean_score[tmp_user_index] for tmp_user_index in both_users])\n",
    "    \n",
    "    similarity = 1 - ssd.cosine(s0, s1) \n",
    "    \n",
    "    if np.isnan(similarity): #s1或s2的l2模为0（全部等于该用户的平均打分）\n",
    "        similarity = 0.0\n",
    "    return similarity  \n",
    "\n",
    "def item_cf_pred(user_index, item_index):\n",
    "    for tmp_item_index in user_2_items[user_index]:\n",
    "        if tmp_item_index == item_index:\n",
    "            return user_item_2_score[user_index, item_index] #已经打过分了,不用估计了\n",
    "        \n",
    "    sim_abs_sum = 0.0\n",
    "    acc = 0.0\n",
    "    #此user打过分的所有item\n",
    "    for tmp_item_index in user_2_items[user_index]:\n",
    "        sim = cal_sim(tmp_item_index, item_index)\n",
    "        if sim != 0:\n",
    "            acc += sim * (user_item_2_score[user_index, tmp_item_index])\n",
    "            sim_abs_sum = np.abs(sim)\n",
    "        \n",
    "    if sim_abs_sum != 0:\n",
    "        pred_score = acc/sim_abs_sum\n",
    "    else:\n",
    "        pred_score = users_mean_score[user_index] #没有找到相似的用户，返回个默认值\n",
    "    \n",
    "    if pred_score < 0:\n",
    "        pred_score = 0.0\n",
    "        \n",
    "    return pred_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def recommend(tar_user):\n",
    "    tar_user_index = users_index[tar_user]\n",
    "    #训练集中该用户打过分的item\n",
    "    tar_user_items = user_2_items[tar_user_index]\n",
    "    #该用户对所有item的打分\n",
    "    tar_user_items_pred_scores = np.zeros(n_items)\n",
    "    \n",
    "    #预测打分\n",
    "    for i in range(n_items):\n",
    "        if i not in tar_user_items:\n",
    "            tar_user_items_pred_scores[i] = item_cf_pred(tar_user_index, i)\n",
    "    \n",
    "    #推荐\n",
    "    sort_index = sorted(((e,i) for i,e in enumerate(list(tar_user_items_pred_scores))), reverse=True)\n",
    "    columns = ['item', 'score']\n",
    "    df = pd.DataFrame(columns=columns)\n",
    "    \n",
    "    for i in range(0,len(sort_index)):\n",
    "        cur_item_index = sort_index[i][1] \n",
    "        cur_item = list (items_index.keys()) [list (items_index.values()).index (cur_item_index)]\n",
    "        \n",
    "        if ~np.isnan(sort_index[i][0]) and cur_item_index not in tar_user_items:\n",
    "            df.loc[len(df)]=[cur_item, sort_index[i][0]]\n",
    "            \n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#读取测试数据\n",
    "triplet_cols = ['user','item', 'score'] \n",
    "\n",
    "df_triplet_test = pd.read_csv(temp_data +'triplet_dataset_test.csv', sep=',', names=triplet_cols, encoding='latin-1', header=0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "E:\\main\\local\\Anaconda3\\envs\\tf1.14\\lib\\site-packages\\scipy\\spatial\\distance.py:720: RuntimeWarning: invalid value encountered in double_scalars\n",
      "  dist = 1.0 - uv / np.sqrt(uu * vv)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "complete:3325fe1d8da7b13dd42004ede8011ce3d7cd205d progress:0.0013774104683195593\n",
      "complete:e82b3380f770c78f8f067f464941057c798eaca2 progress:0.0027548209366391185\n",
      "complete:bdfca47d03157d26f1404075172128a6f8a3d39e progress:0.004132231404958678\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-8-9c4c8132878c>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     21\u001b[0m     \u001b[0muser_records_test\u001b[0m\u001b[1;33m=\u001b[0m \u001b[0mdf_triplet_test\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mdf_triplet_test\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0muser\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0muser\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     22\u001b[0m     \u001b[1;31m#计算推荐item\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 23\u001b[1;33m     \u001b[0mrec_items\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mrecommend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0muser\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     24\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     25\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mRECOMMEND_ITEM_SIZE\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-6-62fc996580ba>\u001b[0m in \u001b[0;36mrecommend\u001b[1;34m(tar_user)\u001b[0m\n\u001b[0;32m      9\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mn_items\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     10\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mtar_user_items\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m             \u001b[0mtar_user_items_pred_scores\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mitem_cf_pred\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtar_user_index\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mi\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     12\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     13\u001b[0m     \u001b[1;31m#推荐\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-5-0ed38949679a>\u001b[0m in \u001b[0;36mitem_cf_pred\u001b[1;34m(user_index, item_index)\u001b[0m\n\u001b[0;32m     33\u001b[0m         \u001b[0msim\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcal_sim\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtmp_item_index\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mitem_index\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     34\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0msim\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 35\u001b[1;33m             \u001b[0macc\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[0msim\u001b[0m \u001b[1;33m*\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0muser_item_2_score\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0muser_index\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtmp_item_index\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     36\u001b[0m             \u001b[0msim_abs_sum\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mabs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msim\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     37\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mE:\\main\\local\\Anaconda3\\envs\\tf1.14\\lib\\site-packages\\scipy\\sparse\\_index.py\u001b[0m in \u001b[0;36m__getitem__\u001b[1;34m(self, key)\u001b[0m\n\u001b[0;32m     37\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrow\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mINT_TYPES\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     38\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcol\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mINT_TYPES\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 39\u001b[1;33m                 \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_intXint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrow\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcol\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     40\u001b[0m             \u001b[1;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcol\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mslice\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     41\u001b[0m                 \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_intXslice\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrow\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcol\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mE:\\main\\local\\Anaconda3\\envs\\tf1.14\\lib\\site-packages\\scipy\\sparse\\compressed.py\u001b[0m in \u001b[0;36m_get_intXint\u001b[1;34m(self, row, col)\u001b[0m\n\u001b[0;32m    644\u001b[0m         indptr, indices, data = get_csr_submatrix(\n\u001b[0;32m    645\u001b[0m             \u001b[0mM\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mN\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mindptr\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mindices\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 646\u001b[1;33m             major, major + 1, minor, minor + 1)\n\u001b[0m\u001b[0;32m    647\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[0mdata\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msum\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdtype\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    648\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "RECOMMEND_ITEM_SIZE = 10\n",
    "\n",
    "n_hits = 0 #击中数目\n",
    "n_total_rec_items = 0 #推荐的item总数(推荐了一个item就加1)\n",
    "n_test_items = 0 #真实的item记录总数()\n",
    "\n",
    "#所有被推荐商品的集合（对不同用户），用于计算覆盖度\n",
    "all_rec_items = set()\n",
    "\n",
    "#统计总的用户\n",
    "unique_users_test = df_triplet_test['user'].unique()\n",
    "\n",
    "#已经计算完毕的用户数\n",
    "complete_user_count = 0\n",
    "\n",
    "for user in unique_users_test:\n",
    "    if user not in users_index:\n",
    "        print(str(user) + 'is new user,\\n') \n",
    "        continue #此user是新用户，无法计算出相似度\n",
    "    #找出test中user的记录集合\n",
    "    user_records_test= df_triplet_test[df_triplet_test.user == user]\n",
    "    #计算推荐item\n",
    "    rec_items = recommend(user)\n",
    "    \n",
    "    for i in range(RECOMMEND_ITEM_SIZE):\n",
    "        item = rec_items.iloc[i]['item']\n",
    "        \n",
    "        if item in user_records_test['item'].values:\n",
    "            n_hits += 1\n",
    "        all_rec_items.add(item)\n",
    "        \n",
    "    #推荐的item总数\n",
    "    n_total_rec_items += RECOMMEND_ITEM_SIZE\n",
    "    \n",
    "    #真实item的总数\n",
    "    n_test_items += user_records_test.shape[0]   \n",
    "    \n",
    "    complete_user_count += 1\n",
    "    print('complete:' + str(user) + \" progress:\" + str(complete_user_count/len(unique_users_test)))\n",
    "\n",
    "#Precision & Recall\n",
    "precision = n_hits / (1.0*n_total_rec_items)\n",
    "recall = n_hits / (1.0*n_test_items)\n",
    "\n",
    "#覆盖度：推荐商品占总需要推荐商品的比例\n",
    "coverage = len(all_rec_items) / (1.0* n_items)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
